using AnQinFrameWorkAPI.DataBase;
using AnQinFrameWorkAPI.Entity.Finance.DTO.FinanceLogin;
using AnQinFrameWorkAPI.Entity.Finance.Entity;
using FrameWork.Request;
using Microsoft.EntityFrameworkCore;
using System.Security.Claims;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Text;

namespace AnQinFrameWorkAPI.Service.Finance;

/// <summary>
///     财务用户登录业务层
/// </summary>
public class FinanceUserLoginService
{
    //数据库
    private readonly DatabaseContext _context;
    
    //配置信息
    private readonly IConfiguration _configuration;

    public FinanceUserLoginService(DatabaseContext context, IConfiguration configuration)
    {
        _context = context;
        _configuration = configuration;
    }

    #region 财务用户登录

    /// <summary>
    ///     财务用户登录
    /// </summary>
    public async Task<RequestResponseModel> FinanceUserLogin(FinanceUserLoginDTO loginDTO, string ip, string deviceInfo)
    {
        var query = await _context.FinanceUser
            .Where(s => s.Account == loginDTO.Account)
            .Select(s => new
            {
                s.Id,
                s.Account,
                s.Password,
                s.Code,
                s.Name
            })
            .AsNoTracking()
            .FirstOrDefaultAsync();

        //找不到账号
        if (query == null) 
        {
            //记录登录失败日志
            await LogLoginAttempt(Guid.Empty, ip, false, "账号不存在", deviceInfo);
            return RequestResponse.BadRequest("账号或者密码错误!", loginDTO.Account);
        }

        //账号或者密码错误
        if (query.Password != loginDTO.Password) 
        {
            //记录登录失败日志
            await LogLoginAttempt(query.Id, ip, false, "密码错误", deviceInfo);
            return RequestResponse.BadRequest("账号或者密码错误!", loginDTO.Account);
        }

        //生成财务专用token
        var token = GenerateFinanceToken(query.Id.ToString(), query.Account, query.Name);

        //记录登录成功日志
        await LogLoginAttempt(query.Id, ip, true, "登录成功", deviceInfo);

        //返回登录结果
        var result = new FinanceUserLoginResultDTO
        {
            Id = query.Id.ToString(),
            Code = query.Code,
            Name = query.Name,
            Token = token,
            LoginTime = DateTime.Now
        };

        return RequestResponse.OK(result, "登录成功");
    }

    #endregion

    #region 生成财务专用Token

    /// <summary>
    ///     生成财务专用Token
    /// </summary>
    private string GenerateFinanceToken(string userId, string account, string name)
    {
        var financeJwtSettings = _configuration.GetSection("FinanceJwtSettings");
        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(financeJwtSettings["SecretKey"]));
        var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

        var claims = new[]
        {
            new Claim(ClaimTypes.NameIdentifier, userId),
            new Claim(ClaimTypes.Name, name),
            new Claim(ClaimTypes.UserData, account),
            new Claim("UserType", "FinanceUser")
        };

        var token = new JwtSecurityToken(
            issuer: financeJwtSettings["Issuer"],
            audience: financeJwtSettings["Audience"],
            claims: claims,
            expires: DateTime.Now.AddMinutes(Convert.ToDouble(financeJwtSettings["ExpireMinutes"])),
            signingCredentials: credentials
        );

        return new JwtSecurityTokenHandler().WriteToken(token);
    }

    #endregion

    #region 记录登录日志

    /// <summary>
    ///     记录登录日志
    /// </summary>
    private async Task LogLoginAttempt(Guid userId, string ip, bool isSuccess, string remark, string deviceInfo)
    {
        var loginRecord = new FinanceUserLoginRecord
        {
            Id = Guid.NewGuid(),
            FinanceUserId = userId,
            LoginIP = ip,
            LoginTime = DateTime.Now,
            IsSuccess = isSuccess,
            Remark = remark,
            DeviceInfo = deviceInfo
        };

        _context.FinanceUserLoginRecord.Add(loginRecord);
        await _context.SaveChangesAsync();
    }

    #endregion

    #region 验证Token

    /// <summary>
    ///     验证财务用户Token
    /// </summary>
    public async Task<RequestResponseModel> ValidateFinanceUserToken(string userId)
    {
        var user = await _context.FinanceUser
            .Where(u => u.Id.ToString() == userId)
            .Select(u => new
            {
                u.Id,
                u.Code,
                u.Name,
                u.Account
            })
            .AsNoTracking()
            .FirstOrDefaultAsync();

        if (user == null)
        {
            return RequestResponse.BadRequest("用户不存在");
        }

        var result = new
        {
            Id = user.Id,
            Code = user.Code,
            Name = user.Name,
            Account = user.Account
        };

        return RequestResponse.OK(result, "验证成功");
    }

    #endregion
}